<template>
  <el-form
    class="form-container"
    ref="ruleFormRef"
    :model="form"
    :label-width="labelWidth"
    :style="{ width: size }"
  >
    <el-row :align="'middle'" :justify="'center'">
      <template v-for="item in formItems">
        <el-col v-bind="itemColLayout">
          <el-form-item
            :label="item.label"
            :prop="item.prop"
            :style="{
              itemStyle: true,
              alignItems: item.type !== 'upload' ? 'center' : 'top',
            }"
            :rules="item.rules"
          >
            <el-input
              v-if="item.type == 'number'"
              v-model="form[`${item.prop}`]"
              :maxlength="item.maxlength"
              :type="item.type"
              :disabled="item.disabled"
              v-bind="item.otherOptions"
              onkeypress="return /[\d]/.test(String.fromCharCode(event.keyCode))"
            />
            <el-input
              v-if="item.type == 'input' || item.type == 'password'"
              v-model="form[`${item.prop}`]"
              :type="item.type"
              :disabled="item.disabled"
              :maxlength="item.maxlength"
              :show-password="item.type === 'password'"
              v-bind="item.otherOptions"
            />
            <!-- 下拉筛选 -->
            <el-select
              v-if="item.type == 'select'"
              v-model="form[`${item.prop}`]"
              v-bind="item.otherOptions"
              style="width: 100%"
              :disabled="item.disabled"
            >
              <el-option
                v-for="option in optionItem[`${item.prop}`] || item.valueEnum"
                :key="option.key"
                :label="option.value"
                :value="option.key"
              ></el-option>
            </el-select>
            <!-- 日期 -->
            <el-date-picker
              v-if="item.type == 'datepicker'"
              v-model="form[`${item.prop}`]"
              v-bind="item.otherOptions"
              :disabled="item.disabled"
            ></el-date-picker>

            <!-- 上传 -->
            <el-upload
              v-if="item.type == 'upload'"
              class="upload-demo"
              :limit="1"
              drag
              ref="upload"
              :on-exceed="handleExceed"
              action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
            >
              <el-icon class="el-icon--upload"><upload-filled /></el-icon>
              <div class="el-upload__text">
                <em>点击</em>或将文件<em>拖拽</em>到这里上传
              </div>
              <template #tip>
                <div class="el-upload__tip"></div>
              </template>
            </el-upload>
          </el-form-item>
        </el-col>
      </template>
    </el-row>
    <div class="footer" v-if="showSubmit">
      <slot name="footer">
        <el-button type="primary" @click="resetBtnClick">重置</el-button>
        <el-button type="primary" @click="searchBtnClick(ruleFormRef)"
          >提交</el-button
        >
      </slot>
    </div>
  </el-form>
</template>

<script setup lang="ts">
import { RuleItem } from "async-validator";
import {
  FormInstance,
  genFileId,
  UploadInstance,
  UploadProps,
  UploadRawFile,
} from "element-plus";
import { StyleValue } from "vue";
const upload = ref<UploadInstance>();

const ruleFormRef = ref<FormInstance>();
interface FormItems {
  label?: string;
  type?: string;
  placeholder?: string;
  rules?: RuleItem;
  prop?: string;
  valueEnum?: Object;
  clearable?: boolean;
  maxlength?: number;
  disabled?: boolean;
  multiple?: boolean;
  optionList?: () => Promise<any[]>;
  width?: number;
  otherOptions?: any;
}

const props = withDefaults(
  defineProps<{
    formItems: Array<FormItems | any>;
    labelWidth?: string;
    itemColLayout?: object;
    itemStyle?: StyleValue;
    showSubmit?: boolean;
    size?: string;
    request: any;
  }>(),
  {
    labelWidth: "80px",

    showSubmit: true,
    itemStyle: () => ({
      padding: "0",
    }),
  }
);
console.log(props.itemStyle);

const formParams = computed(() => {
  let params: any = {};
  props.formItems.map((item) => {
    params[item.prop] = item.value ?? "";
  });
  return params;
});
const form = reactive({ ...formParams.value });
const optionItem = reactive<any>({});
const handleExceed: UploadProps["onExceed"] = (files) => {
  const uploadRef: any = upload.value;
  uploadRef[0].clearFiles();
  const file = files[0] as UploadRawFile;
  file.uid = genFileId();
  uploadRef[0].handleStart(file);
};
// 提交按钮
const searchBtnClick = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
    if (valid) {
      // console.log("submit!", form, props.request);
      props.request && props.request(form);
    } else {
      console.log("error submit!", valid, fields);
    }
  });
};
// 获取下拉数据
const getOptionList = () => {
  props.formItems.map(async (item) => {
    if (!item.optionList) return;
    optionItem[item.prop] = [];
    const res = await item.optionList!();
    optionItem[item.prop].push(...res);
  });
};
getOptionList();

// 重置按钮
const resetBtnClick = () => {
  ruleFormRef.value?.resetFields();
};
defineExpose({ searchBtnClick, ruleFormRef });
</script>

<style lang="scss">
@media screen and (max-width: 1700px) {
  .form-container {
    width: 90% !important;
  }
}
.form-container {
  margin: 0 auto 18px;
  .el-input {
    height: 40px;
  }
  .upload-demo {
    width: 100%;
  }
}
.footer {
  text-align: right;
}
.el-upload-dragger .el-icon--upload {
  color: var(--el-color-primary);
}
</style>
